// N1String.cpp: implementation of the N1String class.
//
//////////////////////////////////////////////////////////////////////

#include "N1String.h"

//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
static int copyNumber(char *number, const char*string)
{
    int count = 0;
    while(isdigit(*string))
    {
        *number++ = *string++;
        count++;
    }
    *number = 0;
    return count;
}

static N1UInt32 getResultLength(const char *format, va_list argptr ) 
{
    N1UInt32 ret = 1;
    va_start( argptr, format);

    while(*format) {

        if(*format!='%')
        {
            ret++;  //Simple chracter
            continue;
        }

        format++;
        //Wait for Flags
        while(*format++) {
            switch(*format)
            {
            case '%':
                ret++;
                continue; 
            case '-':
            case '+':
            case ' ':
            case '0':
            case '#':
                ret++;
                break;
            default:
                break;
            }
        }

        //Wait for Width
        if(isdigit(*format)) {
            char number[10];
            format += copyNumber(number, format);
            int width = atoi(number);
            ret += width;
        } else if(*format=='*') {
            ret += va_arg( argptr, int);
        }

        //Wait for Precision
        if(*format=='.') {
            format++;
            if (isdigit(*format)) {
                char number[10];
                format += copyNumber(number, format);
                int precision = atoi(number);
                ret += precision;
            } else if(*format=='*') {
                ret += va_arg( argptr, int);
            }
        }

        //Wait for Type
        if(1) {
            char str[2];
            const char* ptr;
            strncpy(str, format, 1);
            format++;
            if(!strspn(str, "cCdiouxXeEfgGnpsS"))
                continue;
            switch(str[0])
            {
                case 'c':
                case 'C':
                   ret += 2;
                   va_arg( argptr, int);
                   break;
                case 'd':
                   ret += 9;
                   va_arg( argptr, int);
                   break;
                case 'i':
                   ret += 9;
                   va_arg( argptr, int);
                   break;
                case 'o':
                   ret += 15;
                   va_arg( argptr, int);
                   break;
                case 'u':
                   ret += 9;
                   va_arg( argptr, int);
                   break;
                case 'x':
                   ret += 8;
                   va_arg( argptr, int);
                   break;
                case 'X':
                   ret += 8;
                   va_arg( argptr, int);
                   break;
                case 'e':
                   ret += 21;
                   va_arg( argptr, double);
                   break;
                case 'E':
                   ret += 21;
                   va_arg( argptr, double);
                   break;
                case 'f':
                   ret += 21;
                   va_arg( argptr, double);
                   break;
                case 'g':
                   ret += 21;
                   va_arg( argptr, double);
                   break;
                case 'G':
                   ret += 21;
                   va_arg( argptr, double);
                   break;
                case 'n':
                   ret += 9;
                   va_arg( argptr, int*);
                   break;
                case 'p':
                   ret += 9;
                   va_arg( argptr, void*);
                   break;
                case 's':
                   ptr = va_arg( argptr, const char*);
                   if (ptr)
                       ret += strlen(ptr) * 2;
                   else
                       ret += 9;
                   break;
                case 'S':
                   ptr = va_arg( argptr, const char*);
                   if (ptr)
                       ret += wcslen((const wchar_t*)ptr) * 2;
                   else
                       ret += 9;
                   break;
                default:
                   break;
            }
        }
    }

    va_end( argptr );

    return ret;
}


static const char gEmptyString[] = "";

N1String::N1String() {
    m_nLength = 0;
    m_pStr = (char*)&gEmptyString[0];
}

N1String::~N1String() {
    free();
}

const char* N1String::name() const { 
    return "N1String"; 
}

const char* N1String::description() const { 
    return m_pStr; 
}

void N1String::free() {
    if(m_pStr && m_nLength)
    {
        delete []m_pStr;
    }
}

char * N1String::alloc(N1UInt32 size) {
    char * ret = new char[size];
    return ret;
}

N1String::N1String(const char *string) : m_nLength(0),  m_pStr(NULL) {
    N1UInt32 length = strlen(string);
    m_pStr = alloc(length + 1);
    m_nLength = length + 1;
    strcpy(m_pStr, string);
}

N1String::N1String(const char *string, 
                   N1UInt32 length) : m_nLength(0),  m_pStr(NULL) {
    N1UInt32 realLength = strlen(string);
    m_pStr = alloc(length + 1);
    m_nLength = length + 1;
    strncpy(m_pStr, string, N1Min(realLength,length));
}

N1String::N1String(char c) : m_nLength(0),  m_pStr(NULL) {
    m_pStr = alloc( 2 );
    m_nLength = 2;
    m_pStr[0] = c;
    m_pStr[1] = 0;
}

N1String::N1String(const N1String &string) : m_nLength(0),  m_pStr(NULL) {
    N1UInt32 realLength = strlen( string.cString() );
    m_pStr = alloc(realLength + 1);
    m_nLength = realLength + 1;
    strcpy(m_pStr, string.cString());
}

N1String::N1String(const char* Format, va_list list) {
    N1UInt32 realLength = getResultLength(Format, list);
    m_pStr = alloc(realLength + 1);
    m_nLength = realLength + 1;
    vsprintf(m_pStr, Format, list); 
}

N1String::N1String(const char* Format, ...) : m_nLength(0),  m_pStr(NULL) {
   va_list marker;
   va_start( marker, Format);
   *this = N1String(Format, marker);
   va_end( marker );
}

N1String::operator const char*() const {
   return m_pStr;
}

const N1String& N1String::operator=(const char *string) {
	return *this;
}

const N1String& N1String::operator=(const N1String &string) {
	return *this;
}

const char* N1String::cString() const {
   return m_pStr;
}

N1UInt32 N1String::getLength() const {
   return strlen(m_pStr);
}

void N1String::setBufferSize(N1UInt32 size) {
   char *str = alloc(size);
   str[size - 1] = 0;
   strncpy(str, m_pStr, N1Min(size - 1, m_nLength));
   free();
   m_pStr = str;
   m_nLength = size;
}

char N1String::getAt(N1UInt32 index) const {
   return m_pStr[index];
}

char N1String::setAt(N1UInt32 index, char c) {
   return m_pStr[index] = c;
}

void N1String::append(char c) {
}

void N1String::append(const char *string) {
}

void N1String::append(const char *string, N1UInt32 length) {
}

void N1String::insertAt(N1UInt32 index, const char *string) {
}

void N1String::removeAt(N1UInt32 index, N1UInt32 length) {
}

N1Int32 N1String::find(N1UInt32 from, const char *string) const {
   return 0;
}

void N1String::removeLastPathComponent() {
}

